﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Core;
using System.Drawing;
using System.Collections.ObjectModel;

namespace Silvermoon.Shapes
{
    /// <summary>
    /// Shape the contains other shapes which are rendered sequentially with the same size.
    /// </summary>
    public class MultiShape : Shape
    {
        #region classes

        class ShapeCollection : Collection<Shape>
        {
            private MultiShape ms;

            public ShapeCollection(MultiShape ms)
                : base()
            {
                this.ms = ms;
            }

            public ShapeCollection(MultiShape ms, IList<Shape> shapes)
                : base(shapes)
            {
                this.ms = ms;
            }

            protected override void ClearItems()
            {
                base.ClearItems();
                ms.OnShapesChanged();
            }

            protected override void RemoveItem(int index)
            {
                base.RemoveItem(index);
                ms.OnShapesChanged();
            }

            protected override void InsertItem(int index, Shape item)
            {
                base.InsertItem(index, item);
                ms.OnShapesChanged();
            }
        }

        #endregion

        private ShapeCollection shapes;

        public MultiShape()
            : base()
        {
            this.shapes = new ShapeCollection(this);
        }

        public MultiShape(params Shape[] shapes)
            : base()
        {
            this.shapes = new ShapeCollection(this, shapes);
        }

        public override void Dispose()
        {
            if (shapes != null)
            {
                foreach (Shape shape in shapes)
                {
                    shape.Dispose();
                }
                shapes.Clear();
                shapes = null;
            }
            base.Dispose();
        }

        /// <summary>
        /// Gets a list of shapes.
        /// </summary>
        public IList<Shape> Shapes { get { return shapes; } }

        public IEnumerable<Shape> SetShapes
        {
            set
            {
                if (value != null)
                {
                    foreach (Shape s in value)
                    {
                        shapes.Add(s);
                    }
                }
            }
        }

        public override void Render(Renderer renderer)
        {
            renderer.RenderShapes(shapes);
        }

        protected override void Layout()
        {
            foreach (Shape shape in shapes)
            {
                shape.PreLoad();
            }
            base.Layout();
        }

        /// <summary>
        /// Gets or sets the size of the shape.
        /// </summary>
        /// <value></value>
        public override Size Size
        {
            get
            {
                return base.Size;
            }
            set
            {
                base.Size = value;
                OnLayout();
            }
        }


        protected virtual void OnLayout()
        {
            Size size = Size;
            foreach (Shape shape in shapes)
            {
                shape.Size = size;
            }
        }

        /// <summary>
        /// Gets or sets the color of the shape if the shape supports color.
        /// </summary>
        /// <value></value>
        public override Color Color
        {
            get
            {
                return shapes.Count > 0 ? shapes[0].Color : Color.Empty;
            }
            set
            {
                if (shapes.Count > 0) shapes[0].Color = value;
            }
        }

        protected override Shape CreateClone()
        {
            return new MultiShape();
        }

        protected override void Copy(Shape shape)
        {
            base.Copy(shape);
            MultiShape ms = shape as MultiShape;
            foreach (Shape s in shapes)
            {
                ms.shapes.Add(s.Clone());
            }
        }

        protected virtual void OnShapesChanged()
        {
            Invalidate();
            OnLayout();
        }
    }
}
